package com.qigao.mall.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qigao.mall.api.*;
import com.qigao.mall.channel.config.ChannelConstant;
import com.qigao.mall.commons.dto.*;
import com.qigao.mall.commons.enums.*;
import com.qigao.mall.commons.param.ChannelRespParam;
import com.qigao.mall.commons.param.CommonReqParam;
import com.qigao.mall.commons.po.DivideAppyPo;
import com.qigao.mall.commons.po.DivideDetailPo;
import com.qigao.mall.commons.utils.DateUtil;
import com.qigao.mall.jdbc.mapper.SysUserMapper;
import com.qigao.mall.jdbc.mapper.TbOrderTotalMapper;
import com.qigao.mall.jdbc.mapper.TbPayDetailMapper;
import com.qigao.mall.jdbc.mapper.TbProfitDetailMapper;
import com.qigao.mall.jdbc.model.*;
import com.qigao.mall.service.channel.ChannelService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author luiz
 * @Title: com.qigao.mall.service.impl
 * @ProjectName market-parent
 * @date 2020-06-2020-06-19 14:53
 * @Description:
 */
@Service
public class ProfitDetailServiceImpl implements ProfitDetailService {
    private static final Logger logger=LoggerFactory.getLogger(ProfitDetailServiceImpl.class);
    @Resource
    private TbProfitDetailMapper tbProfitDetailMapper;
    @Resource
    private AccountSerivce accountSerivce;
    @Resource
    private AccountInfoService accountInfoService;
    @Override
    public void insertBatch(List<TbProfitDetail> tbProfitDetails) {
        if(CollectionUtils.isEmpty(tbProfitDetails))return;
        tbProfitDetailMapper.insertBatch(tbProfitDetails);
    }

    @Override
    public void insert(TbProfitDetail tbProfitDetail) {
        tbProfitDetailMapper.insertSelective(tbProfitDetail);
    }

    @Override
    public void saveBatch(List<TbProfitDetail> tbProfitDetails) {
        for(TbProfitDetail tbProfitDetail:tbProfitDetails){
            TbProfitDetail tbProfitDetail1=tbProfitDetailMapper.selectByUniqIndex(tbProfitDetail.getSettleDate(),tbProfitDetail.getUserNo(),tbProfitDetail.getUserLevel(),tbProfitDetail.getItemCode());
            if(tbProfitDetail1!=null){
                tbProfitDetail.setId(tbProfitDetail1.getId());
                tbProfitDetail.setVersion(tbProfitDetail1.getVersion());
                tbProfitDetailMapper.addAmtById(tbProfitDetail);
            }else {
                tbProfitDetailMapper.insertSelective(tbProfitDetail);
            }
        }
    }

    @Override
    public List<TbSettleDetail> selectSettleGroup(Date settleDate) {
        return tbProfitDetailMapper.selectSettleGroup(settleDate);
    }

    @Override
    public List<TbBonusDetail> selectProfitGroup(Date settleDate) {
        return tbProfitDetailMapper.selectProfitGroup(settleDate);
    }

    @Override
    public TbProfitDetail selectUserProfit(String userNo, Date settleDate) {
        return tbProfitDetailMapper.selectUserProfit(userNo,settleDate);
    }

    @Override
    public Result<PageInfo<ProfitDetailResultDto>> listPage(ProfitCondDto profitCondDto) {
        PageHelper.startPage(profitCondDto.getPageNum(),profitCondDto.getPageSize());
        Page<TbProfitDetail> tbProfitDetailPage=(Page<TbProfitDetail>)tbProfitDetailMapper.selectByCond(profitCondDto);
        return convertToDto(tbProfitDetailPage);
    }

    @Override
    public List<ProfitDetailResultDto> findOrderResultByCond(ProfitCondDto profitCondDto) {
        List<TbProfitDetail> tbProfitDetails=(List<TbProfitDetail>)tbProfitDetailMapper.selectByCond(profitCondDto);
        List<ProfitDetailResultDto> profitDetailResultDtos=new ArrayList<>();
        for(TbProfitDetail tbProfitDetail:tbProfitDetails){
            ProfitDetailResultDto profitDetailResultDto=new ProfitDetailResultDto();
            BeanUtils.copyProperties(tbProfitDetail,profitDetailResultDto);
            profitDetailResultDto.setSettleDate(DateUtil.getDateFormat(tbProfitDetail.getSettleDate()));
            profitDetailResultDto.setUserLevelName(UserLevelEnum.getNameByCode(tbProfitDetail.getUserLevel()));
            profitDetailResultDto.setUserTypeName(UserTypeEnum.getNameByCode(tbProfitDetail.getUserType()));
            profitDetailResultDto.setItemTypeName(ItemTypeEnum.getNameByCode(tbProfitDetail.getItemType()));
            profitDetailResultDto.setCreateTime(DateUtil.getDateTimeFormat(tbProfitDetail.getCreateTime()));
            profitDetailResultDto.setModiTime(DateUtil.getDateTimeFormat(tbProfitDetail.getModiTime()));
            profitDetailResultDtos.add(profitDetailResultDto);
        }
        return profitDetailResultDtos;
    }


    private Result<PageInfo<ProfitDetailResultDto>> convertToDto(Page<TbProfitDetail> tbProfitDetailPage) {
        Page<ProfitDetailResultDto> profitDetailResultDtoPage=new Page<ProfitDetailResultDto>();
        BeanUtils.copyProperties(tbProfitDetailPage,profitDetailResultDtoPage);
        if(tbProfitDetailPage.getResult()!=null){
            for(TbProfitDetail tbProfitDetail:tbProfitDetailPage.getResult()){
                ProfitDetailResultDto profitDetailResultDto=new ProfitDetailResultDto();
                BeanUtils.copyProperties(tbProfitDetail,profitDetailResultDto);
                profitDetailResultDto.setSettleDate(DateUtil.getDateFormat(tbProfitDetail.getSettleDate()));
                profitDetailResultDto.setUserLevelName(UserLevelEnum.getNameByCode(tbProfitDetail.getUserLevel()));
                profitDetailResultDto.setUserTypeName(UserTypeEnum.getNameByCode(tbProfitDetail.getUserType()));
                profitDetailResultDto.setItemTypeName(ItemTypeEnum.getNameByCode(tbProfitDetail.getItemType()));
                profitDetailResultDto.setCreateTime(DateUtil.getDateTimeFormat(tbProfitDetail.getCreateTime()));
                profitDetailResultDto.setModiTime(DateUtil.getDateTimeFormat(tbProfitDetail.getModiTime()));
                profitDetailResultDtoPage.add(profitDetailResultDto);
            }
        }
        return Result.newSuccess(new PageInfo<>(profitDetailResultDtoPage));
    }
    @Resource
    private ChannelService channelService;
    @Resource
    private ChannelRouteService channelRouteService;
    @Resource
    private TbPayDetailMapper tbPayDetailMapper;

    @Override
    public void applyDivide(DivideAppyPo divideAppyPo) {
        if(CollectionUtils.isEmpty(divideAppyPo.getDivideDetailPoList())){
            logger.info("团购{}分账对象不能为空",divideAppyPo.getGroupNo());
            return;
        }
        TbPayDetail tbPayDetail= tbPayDetailMapper.selectByPaySeqNo(divideAppyPo.getPaySeqNo());
        if(tbPayDetail==null){
            logger.info("根据付款流水号{}找不到记录，无法分账",divideAppyPo.getPaySeqNo());
            return;
        }
        TbMerChannel tbMerChannel=channelRouteService.findChannelRoute(tbPayDetail.getMerNo(),tbPayDetail.getWebSource(),tbPayDetail.getPayWay());
        if(tbMerChannel==null){
            logger.error("渠道信息不存在:{}",tbPayDetail);
            return ;
        }
        //1.记录付款订单信息
        MerChannelDto merChannelDto=buildMerchantDto(tbMerChannel,tbPayDetail);
        //添加分账用户
        divideAddUser(merChannelDto,divideAppyPo.getDivideDetailPoList());
        //开始分账
        divideAmt(merChannelDto,tbPayDetail,divideAppyPo);
    }

    private void divideAddUser(MerChannelDto merChannelDto,List<DivideDetailPo> divideDetailPos){
        merChannelDto.setProductNo(PayProductEnum.WEICHAT_PROFIT_ADD.getProductCode());
        for(DivideDetailPo divideDetailPo:divideDetailPos){
            logger.info("添加用户:{}",divideDetailPo.getRecvUserNo());
            CommonReqParam commonReqParam=buildAddUserParam(divideDetailPo.getRecvUserNo());
            ChannelRespParam channelRespParam=channelService.channelProcess(merChannelDto,commonReqParam);
            logger.info("渠道返回信息:{}",channelRespParam);
        }
    }

    private void divideAmt(MerChannelDto merChannelDto,TbPayDetail tbPayDetail,DivideAppyPo divideAppyPo) {
        merChannelDto.setProductNo(PayProductEnum.WEICHAT_PROFIT_SHARING.getProductCode());
        CommonReqParam commonReqParam=buildDivideParam(tbPayDetail,divideAppyPo.getDivideDetailPoList());
        ChannelRespParam channelRespParam=channelService.channelProcess(merChannelDto,commonReqParam);
        logger.info("渠道返回信息:{}",channelRespParam);
        if(ChannelCodeEnum.SUCCESS.getCode().equals(channelRespParam.getRespCode())){
            //更新组团明细信息 todo 记录账户记录
        }
    }

    private MerChannelDto buildMerchantDto(TbMerChannel tbMerChannel, TbPayDetail tbPayDetail) {
        MerChannelDto merChannelDto= new MerChannelDto();
        merChannelDto.setMerNo(tbMerChannel.getMerNo());
        merChannelDto.setMerName(tbMerChannel.getMerName());
        merChannelDto.setChannelCode(tbMerChannel.getChannelCode());
        merChannelDto.setChannelAction(ChannelActionEnum.ORDER_DIVIDE.getCode());
        merChannelDto.setAppId(tbMerChannel.getAppId());
        merChannelDto.setAppSecret(tbMerChannel.getAppSecret());
        merChannelDto.setChannelPartenerNo(tbMerChannel.getChannelPartenerNo());
        merChannelDto.setChannelPartenerName(tbMerChannel.getChannelPartenerName());
        merChannelDto.setSignType("HMAC-SHA256");
        merChannelDto.setResvKey(tbMerChannel.getResvKey());
        merChannelDto.setMd5Key(tbMerChannel.getMd5Key());
        merChannelDto.setPrivKey(tbMerChannel.getPrivKey());
        merChannelDto.setPubKey(tbMerChannel.getPubKey());
        merChannelDto.setInnerSeqNo(tbPayDetail.getPaySeqNo());
        merChannelDto.setThirdSeqNo(tbPayDetail.getRespPayNo());
        return merChannelDto;
    }

    private CommonReqParam buildAddUserParam(String recvUserNo) {
        CommonReqParam commonReqParam= new CommonReqParam();
        commonReqParam.setCharsetCode("UTF-8");
        commonReqParam.setRequestTime(DateUtil.getDateTimeFormat(new Date()));
        JSONObject reqContent=new JSONObject();
        reqContent.put("recvUserNo",recvUserNo);
        commonReqParam.setReqContent(reqContent.toString());
        return commonReqParam;
    }

    private CommonReqParam buildDivideParam(TbPayDetail tbPayDetail,List<DivideDetailPo> divideDetailPos) {
        CommonReqParam commonReqParam= new CommonReqParam();
        commonReqParam.setMerNo(tbPayDetail.getMerNo());
        commonReqParam.setCharsetCode("UTF-8");
        commonReqParam.setRequestTime(DateUtil.getDateTimeFormat(new Date()));
        JSONObject reqContent=new JSONObject();
        JSONArray jsonArray=new JSONArray();
        for(DivideDetailPo divideDetailPo:divideDetailPos){
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("recvUserNo",divideDetailPo.getRecvUserNo());
            jsonObject.put("recvAmount",divideDetailPo.getRecvAmt());
            jsonArray.add(jsonObject);
        }
        reqContent.put("receivers",jsonArray);
        commonReqParam.setReqContent(reqContent.toString());
        return commonReqParam;
    }

}
